package codegen

import (
	"os"
	"path/filepath"
	"strings"

	"github.com/progrium/darwinkit/generate/modules"
	"github.com/progrium/darwinkit/internal/set"
	"github.com/progrium/darwinkit/internal/stringx"
)

// TypeWriter write codes for a go file
type FileWriter struct {
	Name        string // usually the header file name, without .h
	Module      modules.Module
	PlatformDir string

	typeCodes []CodeGen
}

func (w *FileWriter) Add(types ...CodeGen) {
	w.typeCodes = append(w.typeCodes, types...)
}

func (w *FileWriter) WriteCode() {
	//fmt.Println("- gen code for", w.Name)
	goFilePath := w.goFilePath()
	fw, err := Create(goFilePath)
	if err != nil {
		panic(err)
	}
	defer fw.Close()
	cw := &CodeWriter{Writer: fw, IndentStr: "\t"}
	cw.WriteLine(AutoGeneratedMark)
	cw.WriteLine("package " + w.Module.Package)

	cw.WriteLine("import (")

	// imports
	var imports = set.New("unsafe")
	for _, tc := range w.typeCodes {
		imports.AddSet(tc.GoImports())
	}
	selfPackage := "github.com/progrium/darwinkit/macos/" + w.Module.Package
	cw.Indent()
	imports.ForEach(func(value string) {
		if value != selfPackage && value != "github.com/progrium/darwinkit/macos/objc" {
			cw.WriteLine("\"" + value + "\"")
		}
	})
	cw.UnIndent()
	cw.WriteLine(")")

	for _, tc := range w.typeCodes {
		tc.WriteGoCode(cw)
	}
}

func (w *FileWriter) goFilePath() string {
	if strings.Contains(w.Name, "Delegate") {
		w.Name = strings.Replace(w.Name, "Protocol", "", -1)
	}
	name := stringx.CamelToSnake(modules.TrimPrefix(w.Name))
	return w.PlatformDir + "/" + w.Module.Package + "/" + name + ".gen.go"
}

func Create(filename string) (*os.File, error) {
	parent := filepath.Dir(filename)
	if err := os.MkdirAll(parent, os.ModePerm); err != nil {
		return nil, err
	}
	return os.Create(filename)
}
